﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using Newtonsoft.Json;
using System.IO;
using System.Runtime.InteropServices;
using IdCardApp.utils;

namespace IdCardApp
{
    public partial class Form1 : Form
    {
        [DllImport("Sdtapi.dll")]
        private static extern int InitComm(int iPort);
        [DllImport("Sdtapi.dll")]
        private static extern int Authenticate();
        [DllImport("Sdtapi.dll")]
        private static extern int ReadBaseInfos(StringBuilder Name, StringBuilder Gender, StringBuilder Folk,
                                                    StringBuilder BirthDay, StringBuilder Code, StringBuilder Address,
                                                        StringBuilder Agency, StringBuilder ExpireStart, StringBuilder ExpireEnd);
        [DllImport("Sdtapi.dll")]
        private static extern int CloseComm();
        [DllImport("Sdtapi.dll")]
        private static extern int ReadBaseMsg(byte[] pMsg, ref int len);
        [DllImport("Sdtapi.dll")]
        private static extern int ReadBaseMsgW(byte[] pMsg, ref int len);

        private HttpListener httpListener;
        private Thread listenThread;
        private Ini ini;

        public Form1()
        {
            InitializeComponent();

            ini = new Ini(Application.StartupPath + "\\config\\settings.ini");
        }

        private void btnServerStart_Click(object sender, EventArgs e)
        {
            if (!httpListener.IsListening)
            {
                StartListener();
            }
            else
            {
                StopListener();
            }           
        }

        private void StopListener()
        {
            if (httpListener != null)
            {
                httpListener.Close();
                pictureBox2.Image = Properties.Resources.onError;
                btnServerStart.Text = "开启服务";
                txtPort.Enabled = true;
                txtHost.Enabled = true;
            }
        }

        private void StartListener()
        {
            try
            {
                httpListener = new HttpListener();

                string host = txtHost.Text; //localhost

                int port = 0;

                if (!int.TryParse(txtPort.Text, out port))
                {
                    port = 8080;
                    txtPort.Text = port.ToString();
                }

                httpListener.Prefixes.Add("http://" + host + ":" + port + "/");
                
                httpListener.Start();
                listenThread = new Thread(AcceptClient);
                listenThread.Name = "httpserver";
                listenThread.Start();

                txtHost.Enabled = false;
                txtPort.Enabled = false;
                btnServerStart.Text = "关闭服务";
                pictureBox2.Image = Properties.Resources.onCorrect;

                ini.WriteValue("app", "host", txtHost.Text);
                ini.WriteValue("app", "port", txtPort.Text);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnServerClose_Click(object sender, EventArgs e)
        {
            if (httpListener != null && httpListener.IsListening)
            {
                httpListener.Close();
            }
        }

        /// <summary>    
        /// /接受客户端请求    
        /// </summary>    
        void AcceptClient()
        {
            while (httpListener.IsListening)
            {
                try
                {
                    HttpListenerContext context = httpListener.GetContext();
                    //new Thread(HandleRequest).Start(context);  
                    ThreadPool.QueueUserWorkItem(new WaitCallback(HandleRequest), context);
                }
                catch (Exception ex)
                {
                    //...
                }
            }

        }

        private void HandleRequest(object ctx)
        {
            HttpListenerContext context = ctx as HttpListenerContext;
            HttpListenerResponse response = context.Response;
            HttpListenerRequest request = context.Request;

            if (request.HttpMethod.ToUpper() == "OPTIONS")
            {
                response.Headers.Add("Access-Control-Allow-Origin", "*");
                response.ContentType = "application/json";
                response.OutputStream.Flush();
                            
                response.Close();
                return;
            }

            if (!request.HasEntityBody)
            {
                response.StatusCode = 403;
                response.Close();
                return;
            }

            StreamReader sr = new StreamReader(request.InputStream);
            string content = sr.ReadToEnd();  //name=XXX&age=XXX

            Logging("接收到请求：" + content);

            Dictionary<string, object> dict = new Dictionary<string, object>();

            try
            {
                Dictionary<string, string> paramDict = new Dictionary<string, string>();

                if (content.IndexOf("=") != -1)
                {
                    string[] pairs = content.Split('&');

                    for (int i = 0; i < pairs.Length; i++)
                    {
                        string[] arr = pairs[i].Split('=');

                        paramDict[arr[0]] = arr[1];
                    }
                }
                else
                {
                    paramDict = JavaScriptConvert.DeserializeObject<Dictionary<string, string>>(content);
                }

                if (paramDict["action"] == "getIdCardInfo")
                {
                    string message = string.Empty;

                    IdCardInfo info = ReadIdCardInfo(out message);

                    if (info != null)
                    {
                        Dictionary<string, object> data = new Dictionary<string, object>();
                        data["code"] = info.Code;
                        data["name"] = info.Name;
                        data["gender"] = info.Gender;
                        data["folk"] = info.Folk;
                        data["birthday"] = info.Birthday;
                        data["address"] = info.Address;
                        data["agency"] = info.Agency;
                        data["expireStart"] = info.ExpireStart;
                        data["expireEnd"] = info.ExpireEnd;

                        data["imageData"] = ConvertImageToBase64(Application.StartupPath + "\\photo.bmp");

                        dict["data"] = data;

                        dict["result"] = true;
                        dict["message"] = message;
                    }
                    else
                    {
                        dict["result"] = false;
                        dict["message"] = message;
                    }
                }
                else
                {
                    dict["result"] = true;
                    dict["message"] = "不支持的命令";
                }
            }
            catch (Exception ex)
            {
                dict["result"] = false;
                dict["message"] = ex.Message;
            }
            
            string output = JavaScriptConvert.SerializeObject(dict);
            byte[] buffer = Encoding.UTF8.GetBytes(output);

            response.Headers.Add("Access-Control-Allow-Origin", "*");
            response.ContentType = "application/json";
            response.OutputStream.Write(buffer,0,buffer.Length);
            response.OutputStream.Flush();

            
            response.Close();
        }

        public string ConvertImageToBase64(string fileName)
        {
            string data = "";

            if (File.Exists(fileName))
            {
                System.Drawing.Bitmap bmp1 = new System.Drawing.Bitmap(fileName);
                using (MemoryStream ms1 = new MemoryStream())
                {
                    bmp1.Save(ms1, System.Drawing.Imaging.ImageFormat.Png);

                    byte[] arr1 = new byte[ms1.Length];
                    ms1.Position = 0;
                    ms1.Read(arr1, 0, (int)ms1.Length);
                    ms1.Close();

                    data = "data:image/png;base64," + Convert.ToBase64String(arr1);
                }   
            }

            return data;
        }

        public IdCardInfo ReadIdCardInfo(out string msg)
        {
            IdCardInfo info = null;

            try
            {
                StringBuilder Name = new StringBuilder(31);
                StringBuilder Gender = new StringBuilder(3);
                StringBuilder Folk = new StringBuilder(10);
                StringBuilder BirthDay = new StringBuilder(9);
                StringBuilder Code = new StringBuilder(19);
                StringBuilder Address = new StringBuilder(71);
                StringBuilder Agency = new StringBuilder(31);
                StringBuilder ExpireStart = new StringBuilder(9);
                StringBuilder ExpireEnd = new StringBuilder(9);

                byte[] pMsg = new byte[256];
                string[] baseinfo = new string[9];
                char[] param = { '\0' };

                //打开端口
                int intOpenRet = InitComm(1001);
                if (intOpenRet != 1)
                {
                    msg = "阅读机具未连接";
                    return null;
                }

                //卡认证
                int intReadRet = Authenticate();
                if (intReadRet != 1)
                {
                    msg = "卡认证失败!请先将身份证拿开，再放置到读卡器上！";
                    CloseComm();
                    return null;
                }
                //三种方式读取基本信息
                //ReadBaseInfos（推荐使用）

                int intReadBaseInfosRet = ReadBaseInfos(Name, Gender, Folk, BirthDay, Code, Address, Agency, ExpireStart, ExpireEnd);
                if (intReadBaseInfosRet != 1)
                {
                    msg = "读卡失败";
                    CloseComm();
                    return null;
                }

                info = new IdCardInfo();

                info.Code = Code.ToString();

                info.Name = Name.ToString();

                info.Gender = Gender.ToString();

                info.Folk = Folk.ToString();

                info.Birthday = BirthDay.ToString();

                info.Address = Address.ToString();

                info.Agency = Agency.ToString();

                info.ExpireStart = ExpireStart.ToString();

                info.ExpireEnd = ExpireEnd.ToString();

                Logging(Name.ToString() + "," + Code.ToString());

                msg = "读卡成功!";

                //关闭端口
                int intCloseRet = CloseComm();
            }
            catch (Exception ex)
            {
                info = null;
                msg = ex.Message;
            }

            return info;
        }

        private void Logging(string str)
        {
            string time = DateTime.Now.ToString("HH:mm:ss");
            
            if (listBox1.Items.Count>10)
            {
                listBox1.Items.RemoveAt(listBox1.Items.Count - 1);    
            }

            listBox1.Invoke(new MethodInvoker(() =>
            {
                listBox1.Items.Insert(0, "[" + time + "]" + str);
            }));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string message = string.Empty;

            IdCardInfo info = ReadIdCardInfo(out message);

            if (info!=null)
            {
                lbCode.Text = info.Code;
                lbName.Text = info.Name;
                lbGender.Text = info.Gender;
                lbFolk.Text = info.Folk;
                lbBirthday.Text = info.Birthday;
                lbAddress.Text = info.Address;
                lbAgency.Text = info.Agency;
                lbExpireStart.Text = info.ExpireStart;
                lbExpireEnd.Text = info.ExpireEnd;

                string photoPath = Application.StartupPath + "\\photo.bmp";

                if (File.Exists(photoPath))
                {
                    picAvatar.Image = Bitmap.FromFile(Application.StartupPath + "\\photo.bmp");                    
                }
            }

            MessageBox.Show(message);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            txtPort.Text = ini.ReadValue("app", "port");
            txtHost.Text = ini.ReadValue("app", "host");
            StartListener();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            string data = ConvertImageToBase64(Application.StartupPath + "\\photo.bmp");


            MessageBox.Show(data);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            StopListener();
        }
    }
}
